package testJdk.net;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.CharsetUtil;
import lombok.SneakyThrows;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/**
 * @author keyer
 * @Description : 服务器简单实现，利用多线程实现同时服务多个客户端
 *
 * 用cmd运行：telnet localhost 10003
 * Created by cyd on 2021-04-29 10:45:57
 */
public class ThreadEchoServer {
    public static void main(String[] args) throws UnknownHostException {
        System.out.println(InetAddress.getLocalHost());
        ServerSocket serverSocket = null;
        int i;

        try {
            i = 1;
            serverSocket = new ServerSocket(10003);
            // 利用死循环来等待外界连接
            while (true) {
                // 利用socket的阻塞特性，让它一直在这里等待连接
                Socket incoming = serverSocket.accept();
                System.out.println("swapping:" + i);
                // 利用多线程的特性，让新的线程去处理新的连接
                Runnable runnable = new ThreadedEchoHandle(incoming);
                Thread thread = new Thread(runnable);
                thread.start();
                i++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class ThreadedEchoHandle implements Runnable {

    /**
     * 与客户端的链接
     */
    private final Socket imcoming;

    public ThreadedEchoHandle(Socket i) {
        imcoming = i;
    }

    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @SneakyThrows
    @Override
    public void run() {
        InputStream inputStream = imcoming.getInputStream();
        OutputStream outputStream = imcoming.getOutputStream();

        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream, true);
        // 向客户端输出提示
        out.println("hello,print bye to exit");

        boolean done = false;
        // 利用输入流的标准处理
        while (!done && in.hasNextLine()) {
            String line = in.nextLine();
            // 转码
            String newLine = Convert.convertCharset(line, CharsetUtil.GBK, "UTF-8");
            // 控制台输出
            System.out.println("client: " + newLine);
            // 对客户端输出
            out.println("echo: " + newLine);
            if ("bye".equals(line.trim())) {
                done = true;
            }
        }
        out.println("server: good bye");
        imcoming.close();
    }
}
